package com.wispx.gateway.core.filter.flow.algorithm;

import com.wispx.gateway.core.context.GatewayContext;
import com.wispx.gateway.core.filter.flow.RateLimiter;

import java.util.Deque;
import java.util.LinkedList;

/**
 * 滑动窗口
 */
public class SlidingWindowRateLimiter implements RateLimiter {

    /**windowsSize毫秒内最大允许capacity次请求**/
    private final int capacity; // 最大允许请求数
    private final int windowsSize; // 窗口大小，单位 ms
    private final Deque<Long> requestTimestamps; // 每个请求的时间戳

    public SlidingWindowRateLimiter(int capacity, int windowsSize) {
        this.capacity = capacity;
        this.windowsSize = windowsSize;
        this.requestTimestamps = new LinkedList<>();
    }

    @Override
    public synchronized void tryConsume(GatewayContext context) {
        long now = System.currentTimeMillis();
        clearOldRequest(now);
        if (requestTimestamps.size() < capacity) {
            requestTimestamps.addLast(now);
            context.doFilter();
        } else {
            throw new RuntimeException("流量到达限流上限，该请求将被丢弃");
        }
    }

    // 清除不在窗口内的请求
    private void clearOldRequest(long now) {
        while (!requestTimestamps.isEmpty() && (now - requestTimestamps.peekFirst() > windowsSize)) {
            requestTimestamps.pollFirst();
        }
    }
}
